<?php
/**
 * Page class definition
 *  
 * @author Sean Crystal <seancrystal@gmail.com>
 * @package MutantVole
 */
require_once 'interfaces/iPresenter.php';
require_once 'interfaces/iViewRenderer.php';
require_once 'interfaces/iSession.php';

/**
 * Base class for pages. Should be extended for each individual page.
 * @package MutantVole
 * @subpackage Pages
 */
abstract class Page extends RequestHandler {
	
	/**
	 * Create presenter, renderer and anything else the page needs to load before
	 * the request can be handled
	 */
	abstract public function Setup();
	
	/**
	 * Setup the Page, handle the Request and render the views
	 * @param Request|null $request
	 * @param iSession|null $session
	 * @param iViewRenderer|null $renderer
	 */
    public function Display(Request $request = null, iSession $session = null, iViewRenderer $renderer = null) {
        if ($request) {
            $this->request = $request;
        }
        
        if ($session) {
			$this->session = $session;
		}

        if ($renderer && empty($this->renderer)) {
            $this->renderer = $renderer;
        }
		
        if ($this->request instanceof Request) {
            $this->SetupHandlers($this->request);
        }
        
        $this->Setup();
        
        if (is_array($this->subPagelets)) {
            foreach ($this->subPagelets as $pagelet) {
                $pagelet->Display($this->request, $this->session, $this->renderer);
            }
        }
        
        if ($this->request instanceof Request) {
            $this->request->Handle();
        }

        if (!$this->renderer instanceof iViewRenderer) {
            throw new PageMissingRendererException(get_class($this));
        }

        $this->renderer->Render();
    }
    
    /**
     * Attach a pagelet as a child to this page
     * @param Pagelet $pagelet
     */
    public function AttachPagelet(Pagelet $pagelet) {
        $this->subPagelets[] = $pagelet;
    }
    
	/**
	 * Convenience method for adding a Presenter and View with a matching prefix, optionally 
	 * attaching it to a parent presenter
	 * @param string $prefix
	 * @param string|null $formName
	 * @param iPresenter|null $parent
	 */
    public function AddPresenter($prefix, $formName = null, iPresenter $parent = null) {
    	Contract::Precondition(!empty($prefix), '$prefix cannot be empty');
    	
        $presenterClass = "{$prefix}Presenter";
        $viewClass = "{$prefix}View";

		if (!class_exists($presenterClass)) {
			throw new ClassNotFoundException($presenterClass);
		}
		
		if (!class_exists($viewClass)) {
			throw new ClassNotFoundException($viewClass);
		}
		
        if ($parent) {
            $parent->AttachSubPresenter(new $presenterClass(new $viewClass($this->renderer, $formName), $this->request, $this->session));

        } else {
            $this->presenter = new $presenterClass(new $viewClass($this->renderer, $formName), $this->request, $this->session);
        }
    }

	/**
	 * application session store instance
	 * @var iSession
	 */
    protected $session;
    
    /**
     * request instance
     * @var Request
     */
    protected $request;
    
    /**
     * view renderer to render the page with
     * @var iViewRenderer
     */
    protected $renderer;
    
    /**
     * the head presenter that all other presenters are attached to
     * @var iPresenter
     */
    protected $presenter;
    
    /**
     * list of attached pagelets
     * @var array
     */
    protected $subPagelets;
}

?>